﻿using System;
using System.Reflection;
using UnityEngine;

namespace MuMech
{
    public static class ReflectionUtils
    {

        public static bool isAssemblyLoaded(string assemblyName)
        {
            foreach (AssemblyLoader.LoadedAssembly assembly in AssemblyLoader.loadedAssemblies)
            {
                try
                {
                    if (assembly.assembly.GetName().Name == assemblyName)
                    {
                        return true;
                    }
                }
                catch (InvalidOperationException)
                {
                    // Silently drop exception generated by users who manage to put assembly that
                    // can't load for reasons (missing deps most of the time)
                }
            }
            return false;
        }

        public static FieldInfo getFieldByReflection(String assemblyString, String className, String fieldName, BindingFlags flags = BindingFlags.Public|BindingFlags.Instance|BindingFlags.Static) {
                string assemblyName = "";

                foreach (AssemblyLoader.LoadedAssembly loaded in AssemblyLoader.loadedAssemblies)
                {
                    if (loaded.assembly.GetName().Name == assemblyString)
                    {
                        assemblyName = loaded.assembly.FullName;
                    }
                }

                if (assemblyName == "")
                {
                    Debug.Log("[MechJeb] ReflectionUtils: could not find assembly " + assemblyString);
                    return null;
                }

                Type type = Type.GetType(className + ", " + assemblyName);

                if (type == null)
                {
                    Debug.Log("[MechJeb] ReflectionUtils: could not find type  " + className + ", " + assemblyName);
                    return null;
                }

                return type.GetField(fieldName, flags);
        }

        public static MethodInfo getMethodByReflection(String assemblyString, String className, String methodName, BindingFlags flags)
        {
            string assemblyName = "";

            foreach (AssemblyLoader.LoadedAssembly loaded in AssemblyLoader.loadedAssemblies)
            {
                if (loaded.assembly.GetName().Name == assemblyString)
                {
                    assemblyName = loaded.assembly.FullName;
                }
            }

            if (assemblyName == "")
            {
                Debug.Log("[MechJeb] ReflectionUtils: could not find assembly " + assemblyString);
                return null;
            }

            Type type = Type.GetType(className + ", " + assemblyName);

            if (type == null)
            {
                Debug.Log("[MechJeb] ReflectionUtils: could not find type  " + className + ", " + assemblyName);
                return null;
            }
            return type.GetMethod(methodName, flags);
        }

        public static MethodInfo getMethodByReflection(String assemblyString, String className, String methodName, BindingFlags flags, Type[] args)
        {
            string assemblyName = "";

            foreach (AssemblyLoader.LoadedAssembly loaded in AssemblyLoader.loadedAssemblies)
            {
                if (loaded.assembly.GetName().Name == assemblyString)
                {
                    assemblyName = loaded.assembly.FullName;
                }
            }

            if (assemblyName == "")
            {
                Debug.Log("[MechJeb] ReflectionUtils: could not find assembly " + assemblyString);
                return null;
            }

            Type type = Type.GetType(className + ", " + assemblyName);

            if (type == null)
            {
                Debug.Log("[MechJeb] ReflectionUtils: could not find type  " + className + ", " + assemblyName);
                return null;
            }
            return type.GetMethod(methodName, flags, null, args, null);
        }
    }
}
